home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / dkbtrace / pbmplus / source / pnm / pnmtotif.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-07  |  9.4 KB  |  341 lines

  1. /*
  2. ** pnmtotiff.c - converts a portable anymap to a Tagged Image File
  3. **
  4. ** Derived by Jef Poskanzer from ras2tif.c, which is:
  5. **
  6. ** Copyright (c) 1990 by Sun Microsystems, Inc.
  7. **
  8. ** Author: Patrick J. Naughton
  9. ** naughton@wind.sun.com
  10. **
  11. ** Permission to use, copy, modify, and distribute this software and its
  12. ** documentation for any purpose and without fee is hereby granted,
  13. ** provided that the above copyright notice appear in all copies and that
  14. ** both that copyright notice and this permission notice appear in
  15. ** supporting documentation.
  16. **
  17. ** This file is provided AS IS with no warranties of any kind.  The author
  18. ** shall have no liability with respect to the infringement of copyrights,
  19. ** trade secrets or any patents by this file or any part thereof.  In no
  20. ** event will the author be liable for any lost revenue or profits or
  21. ** other special, indirect and consequential damages.
  22. */
  23.  
  24. #include "pnm.h"
  25. #include "tiffio.h"
  26.  
  27. #include "ppmcmap.h"
  28. #define MAXCOLORS 256
  29.  
  30. void
  31. main( argc, argv )
  32.     int argc;
  33.     char* argv[];
  34.     {
  35.     int argn;
  36.     char* inf = NULL;
  37.     FILE* ifp;
  38.     xel** xels;
  39.     register xel* xP;
  40.     colorhist_vector chv;
  41.     colorhash_table cht;
  42.     unsigned short red[MAXCOLORS], grn[MAXCOLORS], blu[MAXCOLORS];
  43.     int cols, rows, format, row, colors, i;
  44.     register int col;
  45.     xelval maxval;
  46.     int grayscale;
  47.     TIFF* tif;
  48.     long g3options;
  49.     long rowsperstrip;
  50.     unsigned short compression;
  51.     unsigned short fillorder;
  52.     unsigned short predictor;
  53.     short photometric;
  54.     short samplesperpixel;
  55.     short bitspersample;
  56.     int bytesperrow;
  57.     unsigned char* buf;
  58.     unsigned char* tP;
  59.     char* usage = "[-none|-packbits|-lzw|-g3|-g4] [-msb2lsb|-lsb2msb] [-2d] [-fill] [-predictor n] [-rowsperstrip n] [pnmfile]";
  60.  
  61.     pnm_init( &argc, argv );
  62.  
  63.     argn = 1;
  64.     compression = COMPRESSION_LZW;
  65.     g3options = 0;
  66.     fillorder = FILLORDER_MSB2LSB;
  67.     predictor = 0;
  68.     rowsperstrip = 0;
  69.  
  70.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  71.     {
  72.     if ( pm_keymatch( argv[argn], "-none", 2 ) )
  73.         compression = COMPRESSION_NONE;
  74.     else if ( pm_keymatch( argv[argn], "-packbits", 3 ) ) 
  75.         compression = COMPRESSION_PACKBITS;
  76.     else if ( pm_keymatch( argv[argn], "-lzw", 3 ) ) 
  77.         compression = COMPRESSION_LZW;
  78.     else if ( pm_keymatch( argv[argn], "-g3", 3 ) ) 
  79.         compression = COMPRESSION_CCITTFAX3;
  80.     else if ( pm_keymatch( argv[argn], "-g4", 3 ) ) 
  81.         compression = COMPRESSION_CCITTFAX4;
  82.     else if ( pm_keymatch( argv[argn], "-msb2lsb", 3 ) )
  83.         fillorder = FILLORDER_MSB2LSB;
  84.     else if ( pm_keymatch( argv[argn], "-lsb2msb", 3 ) )
  85.         fillorder = FILLORDER_LSB2MSB;
  86.     else if ( pm_keymatch( argv[argn], "-2d", 2 ) )
  87.         g3options |= GROUP3OPT_2DENCODING;
  88.     else if ( pm_keymatch( argv[argn], "-fill", 2 ) )
  89.         g3options |= GROUP3OPT_FILLBITS;
  90.     else if ( pm_keymatch( argv[argn], "-predictor", 3) )
  91.         {
  92.         ++argn;
  93.         if ( argn == argc || sscanf( argv[argn], "%hu", &predictor ) != 1 )
  94.         pm_usage( usage );
  95.         if ( predictor != 1 && predictor != 2 )
  96.         pm_usage( usage );
  97.         }
  98.     else if ( pm_keymatch( argv[argn], "-rowsperstrip", 2 ) )
  99.         {
  100.         ++argn;
  101.         if ( argn == argc ||
  102.          sscanf( argv[argn], "%ld", &rowsperstrip ) != 1 )
  103.         pm_usage( usage );
  104.         if ( rowsperstrip < 1 )
  105.         pm_usage( usage );
  106.         }
  107.     else
  108.         pm_usage( usage );
  109.     ++argn;
  110.     }
  111.  
  112.     if ( argn != argc )
  113.     {
  114.     inf = argv[argn];
  115.     ifp = pm_openr( inf );
  116.     ++argn;
  117.     }
  118.     else
  119.     {
  120.     inf = "Standard Input";
  121.     ifp = stdin;
  122.     }
  123.  
  124.     if ( argn != argc )
  125.     pm_usage( usage );
  126.  
  127.     xels = pnm_readpnm( ifp, &cols, &rows, &maxval, &format );
  128.     pm_close( ifp );
  129.  
  130.     /* Check for grayscale. */
  131.     switch ( PNM_FORMAT_TYPE(format) )
  132.     {
  133.     case PPM_TYPE:
  134.     pm_message( "computing colormap..." );
  135.     chv = ppm_computecolorhist( xels, cols, rows, MAXCOLORS, &colors );
  136.     if ( chv == (colorhist_vector) 0 )
  137.         {
  138.         pm_message(
  139.         "Too many colors - proceeding to write a 24-bit RGB file." );
  140.         pm_message(
  141.         "If you want an 8-bit palette file, try doing a 'ppmquant %d'.",
  142.         MAXCOLORS );
  143.         grayscale = 0;
  144.         }
  145.     else
  146.         {
  147.         pm_message( "%d colors found", colors );
  148.         grayscale = 1;
  149.         for ( i = 0; i < colors; ++i )
  150.         {
  151.         register xelval r, g, b;
  152.  
  153.         r = PPM_GETR( chv[i].color );
  154.         g = PPM_GETG( chv[i].color );
  155.         b = PPM_GETB( chv[i].color );
  156.         if ( r != g || g != b )
  157.             {
  158.             grayscale = 0;
  159.             break;
  160.             }
  161.         }
  162.         }
  163.     break;
  164.  
  165.     default:
  166.     chv = (colorhist_vector) 0;
  167.     grayscale = 1;
  168.     break;
  169.     }
  170.  
  171.     /* Open output file. */
  172.     tif = TIFFFdOpen( fileno (stdout), "Standard Output", "w" );
  173.     if ( tif == NULL )
  174.     pm_error( "error opening standard output as TIFF file" );
  175.  
  176.     /* Figure out TIFF parameters. */
  177.     switch ( PNM_FORMAT_TYPE(format) )
  178.     {
  179.     case PPM_TYPE:
  180.     if ( chv == (colorhist_vector) 0 )
  181.         {
  182.         samplesperpixel = 3;
  183.         bitspersample = 8;
  184.         photometric = PHOTOMETRIC_RGB;
  185.         bytesperrow = cols * 3;
  186.         }
  187.     else if ( grayscale )
  188.         {
  189.         samplesperpixel = 1;
  190.         bitspersample = pm_maxvaltobits( maxval );
  191.         photometric = PHOTOMETRIC_MINISBLACK;
  192.         bytesperrow = ( cols + i - 1 ) / i;
  193.         }
  194.     else
  195.         {
  196.         samplesperpixel = 1;
  197.         bitspersample = 8;
  198.         photometric = PHOTOMETRIC_PALETTE;
  199.         bytesperrow = cols;
  200.         }
  201.     break;
  202.  
  203.     case PGM_TYPE:
  204.     samplesperpixel = 1;
  205.     bitspersample = pm_maxvaltobits( maxval );
  206.     photometric = PHOTOMETRIC_MINISBLACK;
  207.     i = 8 / bitspersample;
  208.     bytesperrow = ( cols + i - 1 ) / i;
  209.     break;
  210.  
  211.     default:
  212.     samplesperpixel = 1;
  213.     bitspersample = 1;
  214.     photometric = PHOTOMETRIC_MINISBLACK;
  215.     bytesperrow = ( cols + 7 ) / 8;
  216.     break;
  217.     }
  218.  
  219.     if ( rowsperstrip == 0 )
  220.     rowsperstrip = ( 8 * 1024 ) / bytesperrow;
  221.     buf = (unsigned char*) malloc( bytesperrow );
  222.     if ( buf == (unsigned char*) 0 )
  223.     pm_error( "can't allocate memory for row buffer" );
  224.  
  225.     /* Set TIFF parameters. */
  226.     TIFFSetField( tif, TIFFTAG_IMAGEWIDTH, cols );
  227.     TIFFSetField( tif, TIFFTAG_IMAGELENGTH, rows );
  228.     TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, bitspersample );
  229.     TIFFSetField( tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT );
  230.     TIFFSetField( tif, TIFFTAG_COMPRESSION, compression );
  231.     if ( compression == COMPRESSION_CCITTFAX3 && g3options != 0 )
  232.     TIFFSetField( tif, TIFFTAG_GROUP3OPTIONS, g3options );
  233.     if ( compression == COMPRESSION_LZW && predictor != 0 )
  234.     TIFFSetField( tif, TIFFTAG_PREDICTOR, predictor );
  235.     TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, photometric );
  236.     TIFFSetField( tif, TIFFTAG_FILLORDER, fillorder );
  237.     TIFFSetField( tif, TIFFTAG_DOCUMENTNAME, inf );
  238.     TIFFSetField( tif, TIFFTAG_IMAGEDESCRIPTION, "converted PNM file" );
  239.     TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel );
  240.     TIFFSetField( tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip );
  241.     /* TIFFSetField( tif, TIFFTAG_STRIPBYTECOUNTS, rows / rowsperstrip ); */
  242.     TIFFSetField( tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
  243.  
  244.     if ( chv == (colorhist_vector) 0 )
  245.     cht = (colorhash_table) 0;
  246.     else
  247.     {
  248.     /* Make TIFF colormap. */
  249.     for ( i = 0; i < colors; ++i )
  250.         {
  251.         red[i] = (long) PPM_GETR( chv[i].color ) * 65535L / maxval;
  252.         grn[i] = (long) PPM_GETG( chv[i].color ) * 65535L / maxval;
  253.         blu[i] = (long) PPM_GETB( chv[i].color ) * 65535L / maxval;
  254.         }
  255.     TIFFSetField( tif, TIFFTAG_COLORMAP, red, grn, blu );
  256.  
  257.     /* Convert color vector to color hash table, for fast lookup. */
  258.     cht = ppm_colorhisttocolorhash( chv, colors );
  259.     ppm_freecolorhist( chv );
  260.     }
  261.  
  262.     /* Now write the TIFF data. */
  263.     for ( row = 0; row < rows; ++row )
  264.     {
  265.     if ( PNM_FORMAT_TYPE(format) == PPM_TYPE && ! grayscale )
  266.         {
  267.         if ( cht == (colorhash_table) 0 )
  268.         {
  269.         for ( col = 0, xP = xels[row], tP = buf;
  270.               col < cols; ++col, ++xP )
  271.             {
  272.             register unsigned char s;
  273.  
  274.             s = PPM_GETR( *xP );
  275.             if ( maxval != 255 )
  276.             s = (long) s * 255 / maxval;
  277.             *tP++ = s;
  278.             s = PPM_GETG( *xP );
  279.             if ( maxval != 255 )
  280.             s = (long) s * 255 / maxval;
  281.             *tP++ = s;
  282.             s = PPM_GETB( *xP );
  283.             if ( maxval != 255 )
  284.             s = (long) s * 255 / maxval;
  285.             *tP++ = s;
  286.             }
  287.         }
  288.         else
  289.         {
  290.         for ( col = 0, xP = xels[row], tP = buf;
  291.               col < cols; ++col, ++xP )
  292.             {
  293.             register int s;
  294.  
  295.             s = ppm_lookupcolor( cht, xP );
  296.             if ( s == -1 )
  297.             pm_error(
  298.                 "color not found?!?  row=%d col=%d  r=%d g=%d b=%d",
  299.                 row, col, PPM_GETR( *xP ), PPM_GETG( *xP ),
  300.                 PPM_GETB( *xP ) );
  301.             *tP++ = (unsigned char) s;
  302.             }
  303.         }
  304.         }
  305.     else
  306.         {
  307.         register xelval bigger_maxval;
  308.         register int bitshift;
  309.         register unsigned char byte;
  310.         register xelval s;
  311.  
  312.         bigger_maxval = pm_bitstomaxval( bitspersample );
  313.         bitshift = 8 - bitspersample;
  314.         byte = 0;
  315.         for ( col = 0, xP = xels[row], tP = buf; col < cols; ++col, ++xP )
  316.         {
  317.         s = PNM_GET1( *xP );
  318.         if ( maxval != bigger_maxval )
  319.             s = (long) s * bigger_maxval / maxval;
  320.         byte |= s << bitshift;
  321.         bitshift -= bitspersample;
  322.         if ( bitshift < 0 )
  323.             {
  324.             *tP++ = byte;
  325.             bitshift = 8 - bitspersample;
  326.             byte = 0;
  327.             }
  328.         }
  329.         if ( bitshift != 8 - bitspersample )
  330.         *tP++ = byte;
  331.         }
  332.  
  333.     if ( TIFFWriteScanline( tif, buf, row, 0 ) < 0 )
  334.         pm_error( "failed a scanline write on row %d", row );
  335.     }
  336.     TIFFFlushData( tif );
  337.     TIFFClose( tif );
  338.  
  339.     exit( 0 );
  340.     }
  341.